package main

import (
	"log"
	"math/rand"
	"sync"
	"time"
)

/*
一个消费者，多个生产者
*/
func main() {

	rand.Seed(time.Now().UnixNano())
	log.SetFlags(0)

	const Max = 100000
	const NumSenders = 1000
	wgReceivers := sync.WaitGroup{}
	wgReceivers.Add(1)

	dataCh := make(chan int)
	stopCh := make(chan struct{})

	for i := 0; i < NumSenders; i++ {
		go func() {
			for { // 每个生产者都在不停的向 dataCh 发送数据

				/*
					为什么要使用 for 循环？

					如果生产者有三个，没有for 循环。则每个生产者最多生产一次数据
					可能会导致 stopCh 永远不会关闭： value != Max-1

					之后 dataCh 就一直堵塞
				*/

				select {

				case <-stopCh: // 当 stopCh关闭后，此处永远不会堵塞
					return
				default:

				}

				select {
				case <-stopCh: // 如果 stopCh 已经关闭，则表明不需要生产了
					return
				case dataCh <- rand.Intn(Max): // 生产者发送值
				}

			}

		}()
	}
	// 当一个 channel 不被任何 goroutine 使用时， 它将被 GC 掉

	go func() {
		defer wgReceivers.Done()
		for value := range dataCh {
			if value == Max-1 { // 通知 生产者不要生产了
				close(stopCh)

				return
			}
			log.Println(value)
		}
	}()

	wgReceivers.Wait()

}
